package org.biubiu0002.baiblog.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.biubiu0002.baiblog.common.exception.BaiBlogException;
import org.biubiu0002.baiblog.common.exception.BizCodeEnumException;
import org.biubiu0002.baiblog.common.utils.PageUtils;
import org.biubiu0002.baiblog.common.utils.Query;
import org.biubiu0002.baiblog.core.dao.SysRoleDao;
import org.biubiu0002.baiblog.core.localcache.RolePermissionCacheService;
import org.biubiu0002.baiblog.core.model.entity.SysPermissionEntity;
import org.biubiu0002.baiblog.core.model.entity.SysRoleEntity;
import org.biubiu0002.baiblog.core.model.entity.SysRolePermissionEntity;
import org.biubiu0002.baiblog.core.model.vo.PermissionVo;
import org.biubiu0002.baiblog.core.model.vo.req.RolePermissionRelationReqVo;
import org.biubiu0002.baiblog.core.model.vo.res.RolePermissionResVo;
import org.biubiu0002.baiblog.core.service.SysPermissionService;
import org.biubiu0002.baiblog.core.service.SysRolePermissionService;
import org.biubiu0002.baiblog.core.service.SysRoleService;
import org.codehaus.plexus.util.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("sysRoleService")
public class SysRoleServiceImpl extends ServiceImpl<SysRoleDao, SysRoleEntity> implements SysRoleService {

    @Resource
    private RolePermissionCacheService rolePermissionCacheService;

    @Resource
    private SysRolePermissionService sysRolePermissionService;

    @Resource
    private SysPermissionService permissionService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SysRoleEntity> page = this.page(
                new Query<SysRoleEntity>().getPage(params),
                new QueryWrapper<SysRoleEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public List<String> getResourceMethodByNameList(List<String> roles) {
        if(CollectionUtils.isEmpty(roles)){
            return Collections.emptyList();
        }
        List<SysRoleEntity> roleList = this.list(new QueryWrapper<SysRoleEntity>()
                .in("name", roles)
                .eq("is_deleted", 0)
        );
        List<Integer> roleIdList = roleList.stream().map(SysRoleEntity::getId).collect(Collectors.toList());
        return getResourceMethod(roleIdList);
    }

    @Override
    public List<String> getResourceMethod(List<Integer> roles) {
        if(CollectionUtils.isEmpty(roles)){
            return Collections.emptyList();
        }
        List<SysRolePermissionEntity> sysRolePermissionEntities = sysRolePermissionService.getBaseMapper().selectList(new QueryWrapper<SysRolePermissionEntity>()
                .in("role_id", roles));
        List<String> resourceIds = sysRolePermissionEntities.stream().map(SysRolePermissionEntity::getPermissionId).distinct().collect(Collectors.toList());
        if(CollectionUtils.isEmpty(resourceIds)){
            return Collections.emptyList();
        }
        List<SysPermissionEntity> sysPermissionEntities = permissionService.getBaseMapper().selectList(new QueryWrapper<SysPermissionEntity>().in("resource_id", resourceIds));
        return sysPermissionEntities.stream().map(SysPermissionEntity::getMethod).collect(Collectors.toList());

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void relateRolePermission(RolePermissionRelationReqVo reqVo) {
        Integer roleId = reqVo.getRoleId();
        List<String> permissionIdList = reqVo.getPermissionIdList();
        SysRoleEntity sysRoleEntity = getById(roleId);
        if(sysRoleEntity==null){
            throw new BaiBlogException(BizCodeEnumException.RECORD_NOT_EXIST_EXCEPTION);
        }
        if(!StringUtils.equals(sysRoleEntity.getName(),reqVo.getRoleName())){
            //更新名称
            sysRoleEntity.setName(reqVo.getRoleName());
            this.updateById(sysRoleEntity);
        }
        //对应资源先删后增
        sysRolePermissionService.remove(new QueryWrapper<SysRolePermissionEntity>().eq("role_id",roleId));

        List<SysRolePermissionEntity> list = permissionIdList.stream().map(item -> {
            SysRolePermissionEntity sysRolePermissionEntity = new SysRolePermissionEntity();
            sysRolePermissionEntity.setRoleId(roleId);
            sysRolePermissionEntity.setPermissionId(item);
            return sysRolePermissionEntity;
        }).collect(Collectors.toList());
        sysRolePermissionService.saveOrUpdateBatch(list);

        rolePermissionCacheService.refresh(reqVo.getRoleName());
    }

    @Override
    public List<RolePermissionResVo> rolePermissionList() {
        List<SysRolePermissionEntity> sysRolePermissionEntityList = sysRolePermissionService.list();
        List<Integer> roleIds = sysRolePermissionEntityList.stream().map(SysRolePermissionEntity::getRoleId).collect(Collectors.toList());
        List<String> permissionIds = sysRolePermissionEntityList.stream().map(SysRolePermissionEntity::getPermissionId).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(permissionIds)){
            return Collections.emptyList();
        }
        List<SysRoleEntity> sysRoleEntities = this.listByIds(roleIds);
        List<SysPermissionEntity> sysPermissionEntities = permissionService.list(new QueryWrapper<SysPermissionEntity>().in("resource_id", permissionIds));
        Map<Integer, SysRoleEntity> roleIdRoleMap = sysRoleEntities.stream().collect(Collectors.toMap(SysRoleEntity::getId, e -> e, (oldV, newV) -> newV));
        Map<String, SysPermissionEntity> permissionIdPermissionMap = sysPermissionEntities.stream().collect(Collectors.toMap(SysPermissionEntity::getResourceId, e -> e, (oldV, newV) -> newV));

        Map<Integer, List<SysRolePermissionEntity>> roleIdRolePermissionListMap = sysRolePermissionEntityList.stream().collect(Collectors.groupingBy(SysRolePermissionEntity::getRoleId));
        List<RolePermissionResVo> rolePermissionResVoList = new ArrayList<>();
        roleIdRolePermissionListMap.forEach((roleId,rolePermissionList)->{
            RolePermissionResVo rolePermissionResVo = new RolePermissionResVo();
            rolePermissionResVo.setRoleId(roleId);
            rolePermissionResVo.setRoleName(roleIdRoleMap.get(roleId).getName());
            List<PermissionVo> permissionVoList = rolePermissionList.stream().map(item -> {
                PermissionVo permissionVo = new PermissionVo();
                permissionVo.setPermissionId(item.getPermissionId());
                permissionVo.setMethod(permissionIdPermissionMap.get(item.getPermissionId()).getMethod());
                permissionVo.setDescription(permissionIdPermissionMap.get(item.getPermissionId()).getDescription());
                return permissionVo;
            }).collect(Collectors.toList());
            rolePermissionResVo.setPermissionVoList(permissionVoList);
            rolePermissionResVoList.add(rolePermissionResVo);
        });
        return rolePermissionResVoList;
    }

}